#-*- coding:utf-8 -*-

import os

from PyQt4.QtCore import *
from PyQt4.QtGui import *


from MapWidget import *
from dialogs.CreateMapDialog import *
from TabTerrain import *
from TabTeleporters import *
from TabOptions import *
from TabEntities import *

##
# Application main window
#
class MainWindow(QMainWindow):

	def __init__(self):
		QMainWindow.__init__(self)

		self.filename = None # current filename

		self.setWindowTitle("XML Map Editor")
		self.setWindowIcon(QIcon("icons/application.png"))

		# widgets --------------------------------------------------------------

		main_widget = QWidget()
		self.setCentralWidget(main_widget)
		main_layout = QHBoxLayout()
		main_widget.setLayout(main_layout)

		# left-side: tabs
		tab_panel = QTabWidget()
		self.tab_terrain = TabTerrain()
		index = tab_panel.addTab(self.tab_terrain, "Tiles")
		tab_panel.setCurrentIndex(index)
		tab_panel.setTabToolTip(index, "Build zone background using tiles")

		tab_entities = TabEntities()
		index = tab_panel.addTab(tab_entities, "Entities")
		tab_panel.setTabToolTip(index, "Place an entity in the current zone")

		index = tab_panel.addTab(TabTeleporters(), "Teleporters")
		tab_panel.setTabToolTip(index, "Manage teleporters in the current zone")

		index = tab_panel.addTab(TabOptions(), u"Options")
		tab_panel.setTabToolTip(index, "Current zone options")

		main_layout.addWidget(tab_panel)

		# right-side: map edition

		right_layout = QVBoxLayout()
		main_layout.addLayout(right_layout)
		self.map_widget = MapWidget()
		self.map_widget.set_tileset(self.tab_terrain.get_tileset())

		self.connect(tab_entities, SIGNAL("mob_selected"), self.map_widget.on_mob_selected)
		self.connect(tab_entities, SIGNAL("decor_selected"), self.map_widget.on_decor_selected)
		self.connect(tab_entities, SIGNAL("item_selected"), self.map_widget.on_item_selected)


		right_layout.addWidget(self.map_widget)

		btn_zone_navigation = QPushButton("Navigate")
		right_layout.addWidget(btn_zone_navigation)

		menubar = self.menuBar()

		# file menu ------------------------------------------------------------

		ac_new = QAction(QIcon("icons/document-new.png"), "New", self)
		ac_new.setShortcut("Ctrl+N")
		ac_new.triggered.connect(self.new_map)

		ac_open = QAction(QIcon("icons/document-open.png"), "Open", self)
		ac_open.setShortcut("Ctrl+O")
		ac_open.triggered.connect(self.open_map_dialog)

		ac_save = QAction(QIcon("icons/document-save.png"), "Save", self)
		ac_save.setShortcut("Ctrl+S")
		ac_save.triggered.connect(self.save)

		ac_save_as = QAction(QIcon("icons/document-save-as.png"), "Save as", self)
		ac_save_as.setShortcut("Ctrl+Shift+S")
		ac_save_as.triggered.connect(self.save_as)

		ac_export_img = QAction(QIcon("icons/export-image.png"), "Export to image", self)
		ac_export_img.triggered.connect(self.export_to_image)

		ac_close = QAction(QIcon("icons/application-exit.png"), "Quit", self)
		ac_close.setShortcut('Ctrl+Q')
		ac_close.triggered.connect(self.close)

		menu_file = menubar.addMenu("&File")
		menu_file.addAction(ac_new)
		menu_file.addAction(ac_open)
		menu_file.addAction(ac_save)
		menu_file.addAction(ac_save_as)
		menu_file.addAction(ac_export_img)
		menu_file.addSeparator()
		menu_file.addAction(ac_close)

		# edit menu ------------------------------------------------------------

		ac_undo = self.map_widget.get_undo_stack().createUndoAction(self)
		ac_undo.setIcon(QIcon("icons/edit-undo.png"))
		ac_undo.setShortcut("Ctrl+Z")

		ac_redo = self.map_widget.get_undo_stack().createRedoAction(self)
		ac_redo.setIcon(QIcon("icons/edit-redo.png"))
		ac_redo.setShortcut("Ctrl+Shift+Z")

		ac_fill = QAction(QIcon("icons/edit-fill.png"), "Fill with active tile", self)
		ac_fill.setStatusTip("Paint the entire zone with selected tile")
		ac_fill.triggered.connect(self.map_widget.fill_with_active_tile)

		menu_edit = menubar.addMenu("&Edit")
		menu_edit.addAction(ac_undo)
		menu_edit.addAction(ac_redo)
		menu_edit.addSeparator()
		menu_edit.addAction(ac_fill)

		# map menu -------------------------------------------------------------

		ac_map_props = QAction(QIcon("icons/configure.png"), "Properties", self)

		ac_zone_up = QAction(QIcon("icons/go-up.png"), "Go north", self)
		ac_zone_up.setShortcut(Qt.Key_Up)
		ac_zone_up.triggered.connect(lambda: self.map_widget.move_zone(0, -1))

		ac_zone_down = QAction(QIcon("icons/go-down.png"), "Go south", self)
		ac_zone_down.setShortcut(Qt.Key_Down)
		ac_zone_down.triggered.connect(lambda: self.map_widget.move_zone(0, 1))

		ac_zone_left = QAction(QIcon("icons/go-previous.png"), "Go east", self)
		ac_zone_left.setShortcut(Qt.Key_Left)
		ac_zone_left.triggered.connect(lambda: self.map_widget.move_zone(-1, 0))

		ac_zone_right = QAction(QIcon("icons/go-next.png"), "Go west", self)
		ac_zone_right.setShortcut(Qt.Key_Right)
		ac_zone_right.triggered.connect(lambda: self.map_widget.move_zone(1, 0))

		menu_map = menubar.addMenu("&Map")
		menu_map.addAction(ac_zone_up)
		menu_map.addAction(ac_zone_down)
		menu_map.addAction(ac_zone_left)
		menu_map.addAction(ac_zone_right)
		menu_map.addSeparator()
		menu_map.addAction(ac_map_props)


		# display menu ---------------------------------------------------------

		ac_show_grid = QAction("Show grid", self)
		ac_show_grid.setCheckable(True)
		ac_show_grid.setShortcut("G")
		ac_show_grid.toggled.connect(self.map_widget.toggle_grid)

		menu_display = menubar.addMenu("&View")
		menu_display.addAction(ac_show_grid)

		# help menu ------------------------------------------------------------

		ac_about = QAction(QIcon("icons/dialog-information.png"), "About", self)
		ac_about.triggered.connect(self.about)

		ac_about_qt = QAction(QIcon("icons/dialog-information.png"), "About Qt", self)
		ac_about_qt.triggered.connect(qApp.aboutQt)

		menu_help = menubar.addMenu("&About")
		menu_help.addAction(ac_about)
		menu_help.addAction(ac_about_qt)

		# tool bar -------------------------------------------------------------

		toolbar = self.addToolBar("Toolbar")
		toolbar.addAction(ac_new)
		toolbar.addAction(ac_open)
		toolbar.addAction(ac_save)
		toolbar.addSeparator()
		toolbar.addAction(ac_undo)
		toolbar.addAction(ac_redo)

		# status bar -----------------------------------------------------------

		self.statusBar().showMessage("Ready")
		self.resize(800, 600)


	##
	# Create a new map document
	#
	def new_map(self):
		dialog = CreateMapDialog(self)
		dialog.exec_()
		if dialog.isValidated():
			try:
				props = dialog.getMapProperties()

				# load tileset
				self.tab_terrain.load_tileset(props["tileset"])

				# load map
				self.map_widget.create_empty_map(props)

				self.set_document_name(None)
				self.statusBar().showMessage("Empty map created")
			except IOError as e:
				QMessageBox.critical(self, "Cannot create map", str(e))

	##
	# Show open map dialog
	#
	def open_map_dialog(self):
		# QString to str
		path = QFileDialog.getOpenFileName(self, "Open", ".", "XML Map (*.xml);;All (*)")
		if path:
			self.open_map(str(path))

	##
	# Open an XML map file
	#
	def open_map(self, path):
		try:
			content = open(path).read()
			document = QDomDocument()
			success, error_msg, line, col = document.setContent(content)
			if not success:
				raise IOError("%s (line %d, column %d)" % (error_msg, line, col))
		except IOError as e:
			QMessageBox.critical(self, "Cannot open map", str(e))
		else:
			# load tileset
			root = document.documentElement()
			tileset_path = os.path.join(os.path.dirname(path), str(root.attribute("tileset")))
			self.tab_terrain.load_tileset(tileset_path)

			# load map
			self.map_widget.load_from_xml(document)

			self.set_document_name(path)
			self.statusBar().showMessage("Map %s opened" % path)

	##
	# Save current map to an XML file
	#
	def save(self):
		if not self.filename:
			self.save_as()

		elif self.map_widget.is_loaded():

			tileset_filename = self.tab_terrain.get_tileset().get_filename()
			# tileset is path relative to map path

			tileset_path = os.path.relpath(tileset_filename, os.path.dirname(self.filename))
			print "saved map to:", self.filename, "#tileset:", tileset_filename, "#relative tileset:", tileset_path
			# link tileset to map
			self.map_widget.set_tileset_filename(tileset_path)
			self.map_widget.save_to_xml(self.filename)
			self.statusBar().showMessage(u"Map %s saved" % self.filename)

	##
	# Save current map to an XML file with a different filename
	#
	def save_as(self):
		if self.map_widget.is_loaded():
			filename = str(QFileDialog.getSaveFileName(self, "Save as", ".", "XML Map (*.xml);;All (*)"))
			if filename:
				self.set_document_name(filename)
				self.save()


	##
	# Ask image filename to export current map
	#
	def export_to_image(self):
		if self.map_widget.is_loaded():
			filename = str(QFileDialog.getSaveFileName(self, "Export to image", ".", "PNG image (*.png)"))
			if filename:
				self.map_widget.save_to_png(filename)
				self.statusBar().showMessage(u"Map exported to " + filename)

	def close(self):
		#TODO: check document
		QMainWindow.close(self)

	##
	# Set current document name and display it in the title bar
	#
	def set_document_name(self, filename):
		self.filename = filename
		if filename:
			self.setWindowTitle(u"XML Map Editor (%s)" % os.path.basename(filename))
		else:
			self.setWindowTitle("XML Map Editor")

	##
	# Show about dialog
	#
	def about(self):
		import __main__
		QMessageBox.about(self, u"About", (
			"%(__doc__)s<br /><br />" +
			"Author: %(__author__)s &lt;%(__email__)s&gt;<br />" +
			"Website: <a href=\"%(__site__)s\">%(__site__)s</a>") % __main__.__dict__
		)
